/*
 * File     : EnumBitFieldHelper.java
 * Created  : 23 Jul 2011
 *
 * Copyright © 2011 Matthew Wilson (mj. {my-surname} .uk {at} gmail.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.googlecode.dni.type.cenum;

import com.googlecode.dni.DirectNativeInterface;

/**
 * <p>
 *  Provides helper methods for dealing with a bit field segment containing an
 *  enum value.
 * </p>
 * <p>
 *  The Java enum will be treated as though it were passed into a library
 *  method; that is, the values should be annotated with {@link CEnumValue} as
 *  appropriate.  If the segment does not start at bit zero, the values are
 *  optionally shifted left; for example, an enum value of 4 for a segment
 *  starting at bit 10 could become <code>4&lt;&lt;10</code> in the bit field;
 *  see the documentation on the factory method for more information.
 * </p>
 * <p>
 *  See {@link MaskBitFieldHelper} for an example.
 * </p>
 *
 * @param <E>
 *           the enum type
 *
 * @see MaskBitFieldHelper
 * @see DirectNativeInterface#getEnumBitFieldHelper(Class,int,int)
 *
 * @author Matthew Wilson
 */
public interface EnumBitFieldHelper< E extends Enum< E > >
{

    /**
     * Takes the given field value and replaces this segment with the given
     * enum value.
     *
     * @param field
     *           the existing field value
     * @param enumValue
     *           the enum value
     * @return the updated field value
     */
    int with( int field, E enumValue );

    /**
     * Determines the enum value that is set in the given field value.
     *
     * @param field
     *            the field value
     * @return the enum value;
     *         if the value is not recognised and an
     *         {@linkplain CEnumUnknownValue unknown value} is defined, that
     *         unknown value will be returned;
     *         otherwise, if the value is not recognised, <code>null</code> will
     *         be returned
     */
    E get( int field );

    /**
     * <p>
     *  Forms a string for debugging purposes that indicates which of the enum
     *  values used by this helper are set in the given field.
     * </p>
     * <p>
     *  The string format is implementation-, platform-, and
     *  version-dependent.
     * </p>
     *
     * @param field
     *            the field value
     * @return a string representation
     */
    String toString( int field );


    /**
     * <p>
     *  Helper interface for enum types that are to be used with
     *  {@link EnumBitFieldHelper}.
     * </p>
     * <p>
     *  The methods can delegate to a static {@link EnumBitFieldHelper} instance
     *  as given in the {@linkplain MaskBitFieldHelper example}.
     * </p>
     *
     * @param <E>
     *           the enum type
     *
     * @author Matthew Wilson
     */
    public interface EnumBitField< E extends Enum< E > & EnumBitField< E > >
    {
        /**
         * <p>
         *  Takes the given field value and replaces this segment with this enum
         *  value.
         * </p>
         * <p>
         *  Implement this as:
         * </p>
         * <pre>
         *  return HELPER.with( field, this );
         * </pre>
         *
         * @param field
         *           the existing field value
         * @return the updated field value
         */
        int set( int field );

        /**
         * <p>
         *  Determines whether this enum value is the value set in the given
         *  field value.
         * </p>
         * <p>
         *  Implement this as:
         * </p>
         * <pre>
         *  return HELPER.get( field ) == this;
         * </pre>
         *
         * @param field
         *            the field value
         * @return <code>true</code> iff the field
         *
         */
        boolean is( int field );
    }

}
